package com.mydemo.likedy.Service.Impl;

import cn.hutool.captcha.CircleCaptcha;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mydemo.likedy.Constant.RedisConstant;
import com.mydemo.likedy.Service.EmailService;
import com.mydemo.likedy.Service.UserLoginService;
import com.mydemo.likedy.Service.UserRegisterService;
import com.mydemo.likedy.Service.UserService;
import com.mydemo.likedy.Utils.RedisCacheUtil;
import com.mydemo.likedy.Utils.SedCaptchaUtil;
import com.mydemo.likedy.exception.BaseException;
import com.mydemo.likedy.mapper.CaptchMapper;
import com.mydemo.likedy.mapper.UserMapper;
import com.mydemo.likedy.pojo.dto.EmailDTO;
import com.mydemo.likedy.pojo.dto.FindPasswordDTO;
import com.mydemo.likedy.pojo.dto.RegisterDTO;
import com.mydemo.likedy.pojo.dto.UserDTO;
import com.mydemo.likedy.pojo.entity.Captcha;
import com.mydemo.likedy.pojo.entity.User;
import com.mydemo.likedy.properties.CaptchaProperties;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


@Service
public class UserLoginServiceImpl extends ServiceImpl<CaptchMapper, Captcha> implements UserLoginService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CaptchaProperties captchaProperties;
    @Autowired
    private EmailService emailService;
    @Autowired
    private UserRegisterService userRegisterService;
    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Autowired
    private UserService userService;

    @Override
    public User userLogin(UserDTO userDTO) {
        LambdaQueryWrapper<User> lambdaQuery = Wrappers.lambdaQuery();
        String Md5password = DigestUtils.md5DigestAsHex(userDTO.getPassword().getBytes());
        lambdaQuery.eq(User::getEmail, userDTO.getEmail());
        User user = userMapper.selectOne(lambdaQuery);
        if (ObjectUtils.isEmpty(user)) {
            throw new BaseException("没有该账号");
        }

        if (!Md5password.equals(user.getPassword())) {
            throw new BaseException("密码不一致");
        }
        return user;
    }

    @Override
    public void captcha(String uuId, HttpServletResponse response) throws IOException {
        if (ObjectUtils.isEmpty(uuId)) throw new IllegalArgumentException("uuid不能为空");
        CircleCaptcha circleCaptcha = SedCaptchaUtil.CreateCircleCaptcha(captchaProperties.getWidth(), captchaProperties.getHigh(), captchaProperties.getCodeCount(), captchaProperties.getLineCount(), uuId);
        String code = circleCaptcha.getCode();
        String format = "yyyy-MM-dd HH:mm:ss";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        String expireTime = LocalDateTime.now().plusMinutes(5).format(dateTimeFormatter);
        Captcha captcha = new Captcha(uuId, code, expireTime);
        this.save(captcha);
        response.setContentType("image/png");//告诉浏览器输出内容为图片
        response.setHeader("Pragma", "No-cache");//禁止浏览器缓存
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        ServletOutputStream out = response.getOutputStream();
        out.write(circleCaptcha.getImageBytes());
    }

    @Override
    public boolean validate(EmailDTO emailDTO) {
        String email = emailDTO.getEmail();
        final String code1 = emailDTO.getCode();
        Captcha captcha = this.getOne(new LambdaQueryWrapper<Captcha>().eq(Captcha::getUuid, emailDTO.getUuid()));
        if (captcha == null) throw new BaseException("uuId为空");

        this.remove(new LambdaQueryWrapper<Captcha>().eq(Captcha::getUuid, emailDTO.getUuid()));
        if (!captcha.getCode().equals(code1)) {
            throw new BaseException("code错误");
        }
        if (LocalDateTime.now().isAfter(LocalDateTime.parse(captcha.getExpireTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))) {
            throw new BaseException("uuid过期");
        }
        if (!code1.equals(captcha.getCode())) {
            return false;
        }

        String code = getSixCode();
        redisCacheUtil.set(RedisConstant.EMAIL_CODE + email, code, RedisConstant.EMAIL_CODE_TIME);
        emailService.send(email, "注册验证码:" + code + ",验证码5分钟之内有效");
        return true;
    }

    /**
     * 生成6位邮箱验证码
     *
     * @return
     */
    public static String getSixCode() {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int code = (int) (Math.random() * 10);
            builder.append(code);
        }
        return builder.toString();
    }

    /**
     * 从redis中获得验证码比较
     *
     * @param email
     * @param code
     * @return
     */

    @Override
    public boolean checkCode(String email, Integer code) {
        if (ObjectUtils.isEmpty(email) || ObjectUtils.isEmpty(code)) {
            throw new BaseException("参数为空");
        }
        final Object o = redisCacheUtil.get(RedisConstant.EMAIL_CODE + email);

        if (!code.toString().equals(o)) {
            throw new BaseException("验证码不正确");

        }
        return true;

    }

    /**
     * 注册并删除注册后数据储存的图形验证码
     *
     * @param registerDTO
     * @return
     */
    @Override
    public boolean register(RegisterDTO registerDTO) {

        // 注册成功后删除图形验证码
        if (userRegisterService.register(registerDTO)) {
            this.removeById(registerDTO.getUuid());
            return true;
        }
        return false;
    }

    /**
     * 找回密码
     *
     * @param findPasswordDTO
     * @return
     */
    @Override
    public Boolean findPassword(FindPasswordDTO findPasswordDTO) {
        final Boolean b = userService.findPassword(findPasswordDTO);
        return b;
    }
}
